﻿using System;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;

namespace AreaBuilder {
    public class ItemReport {
        readonly TextWriter txt;
        readonly StringBuilder output = new StringBuilder();
        readonly StringBuilder items = new StringBuilder();
        readonly StringBuilder render = new StringBuilder();

        public ItemReport(String title) {
            txt = File.CreateText(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), String.Format("{0}.html", title)));
            
            output.AppendLine("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
            output.AppendLine("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
            output.AppendLine("<head>");
            output.AppendLine("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />");
            output.AppendLine(String.Format("<title>Item Report: {0}</title>", title));
            output.AppendLine("</head>");
            output.AppendLine("");
            output.AppendLine("<body>");
            output.AppendLine("<table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">");
            output.AppendLine("[ITEMS]");
            output.AppendLine("</table>");
            output.AppendLine("<hr />");
            output.AppendLine("<pre>");
            output.AppendLine("[RENDER]");
            output.AppendLine("</pre>");
            output.AppendLine("</body>");
            output.AppendLine("</html>");
        }

        public void AddItem(Item i) {
            items.AppendLine(String.Format("<tr><td><a href='#{0}'>{1}</a></td></tr>", i.VNum, i.Keywords));

            render.AppendLine(String.Format("<a name='{0}'></a>This perfect level {1} '{2}' is type {3}.", i.VNum, i.Level, i.Keywords, i.ItemType));
            render.AppendLine(String.Format("Description (Short): {0}", i.Name));
            render.AppendLine(String.Format("Description (Long): {0}", i.Description));
            render.AppendLine(String.Format("Extra flags: {0}.", Expand("extraFlags", "flag", i.ExtraFlags) ?? "none"));
            render.AppendLine(String.Format("Anti-flags: {0}.", String.IsNullOrEmpty(i.V5) ? "none" : i.V5));

            if (ValidArmor(i.ItemType)) {
                render.AppendLine(String.Format("Armor class is {0} pierce, {1} bash, {2} slash, and {3} vs. magic.", i.V0, i.V1, i.V2, i.V3));
                render.AppendLine(String.Format("Bulk value: {0}", i.V4));
            } else if (ValidWeapon(i.ItemType))
                render.AppendLine(String.Format("Weapons flags: {0}", Expand("weaponFlags", "flag", i.V4)));

            var iaQuery = from ItemAffect ia in i.Affects orderby ia.AffectType select ia;
            var itQuery = from ItemTrigger it in i.Triggers orderby it.TriggerType select it;
            var ifQuery = from ItemFlag iFlag in i.Flags orderby iFlag.FlagType select iFlag;

            foreach (ItemAffect ia in iaQuery)
                render.AppendLine(String.Format("Affects {0} by {1}.", Funcs.getXPathSingle(String.Format("/types/locFlags/loc[@value='{0}']", ia.AffectType)).ToLower(), ia.AffectValue));

            foreach (ItemFlag iF in ifQuery) {
                render.AppendLine(String.Format("Affects {0} by {1}.", Funcs.getXPathSingle(String.Format("/types/locFlags/loc[@value='{0}']", iF.FlagLocation)).ToLower(), iF.FlagValue));

                String[] flags = Regex.Split(iF.FlagBits, "");

                foreach (String s in flags) {
                    if (String.IsNullOrEmpty(s)) continue;

                    String temp = Funcs.getXPathSingle(String.Format("/types/affect/flag[@type='{0}']", s)).ToLower();
                    render.AppendLine(String.Format("Adds {0} affect.", temp));
                }
            }

            foreach (ItemTrigger it in itQuery)
                render.AppendLine(String.Format("ObjProg: Trig({0}) Charges(-{1}/-{1}) Command({2})", it.TriggerType, it.TriggerCount, it.TriggerSpell));

            render.AppendLine(String.Format(""));
        }

        private static bool ValidWeapon(IEquatable<string> type) {
            if (type.Equals("weapon")) return true;
            // else if (type.Equals("")) return true;


            return false;
        }

        private static bool ValidArmor(IEquatable<string> type) {
            if (type.Equals("armor")) return true;
            if (type.Equals("jewelry")) return true;
            if (type.Equals("clothing")) return true;
            // else if (type.Equals("")) return true;


            return false;
        }

        private static String Expand(String tree, String subtree, String text) {
            String[] flags = Regex.Split(text, "");
            StringBuilder sb = new StringBuilder();

            foreach (String s in flags) {
                if (String.IsNullOrEmpty(s)) continue;
                sb.Append(Funcs.getXPathSingle(String.Format("/types/{0}/{1}[@value='{2}']", tree, subtree, s)));
                sb.Append(" ");
            }

            return (String.IsNullOrEmpty(sb.ToString()) ? null : sb.ToString().ToLower().Trim());
        }

        public void Render() {
            String strOutput = output.ToString();
            strOutput = strOutput.Replace("[ITEMS]", items.ToString());
            strOutput = strOutput.Replace("[RENDER]", render.ToString());

            txt.Write(strOutput);
            
            txt.Close();    
        }
    }
}
